package com.th.apicenter.rta.util;





import java.lang.reflect.Method;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
//@EnableAspectJAutoProxy
public class AopLogConfig {
    private final static Logger logger = LoggerFactory.getLogger(AopLogConfig.class);
    private final ObjectMapper objectMapper = new ObjectMapper();

    private long maxReduceTime;




    //这里改为自己项目相应的aop表达式
    @Pointcut("execution(public * com.th.apicenter.rta.*.*(..))")
    public void allFunctions() {}

    @Around("allFunctions()")
    public Object processLog(ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        Assert.notNull(attributes, "请求参数null异常");
        HttpServletRequest request = attributes.getRequest();
        String methodName = method.getName();
        logger.info("================== start ==================");
        logger.info("【请求URL】:  {}", request.getRequestURL().toString());
//        logger.info("【请求类型】:  {}", request.getMethod());
//        logger.info("【请求Controller】:  {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
//        logger.info("【来源IP】:  {}", ipInfoUtil.getIpAddr(request));
        try {
            logger.info("【请求入参】:  {}", objectMapper.writeValueAsString(joinPoint.getArgs()));
        } catch (JsonProcessingException e) {
            logger.error("获取请求参数失败");
        }
        long startTime = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        this.printExecTime(methodName, startTime, endTime);
        if (proceed != null) {
            try {
                logger.info("【请求出参】:  {}", objectMapper.writeValueAsString(proceed));
            } catch (JsonProcessingException e) {
                logger.error("获取出参信息失败");
            }
        } else {
            logger.info("【请求出参】:  无出参信息");
        }
        logger.info("=================== end ===================");
        return proceed;
    }

    private void printExecTime(String methodName, long startTime, long endTime) {
        long diffTime = endTime - startTime;
        if (diffTime > maxReduceTime) {
            logger.info("【可能慢接口】:  " + methodName + "【方法执行耗时】:" + diffTime + " ms");
        } else {
            logger.info(methodName + " 【方法执行耗时】:" + diffTime + " ms");
        }
    }
    @Before("allFunctions()")
    public void doBefore(JoinPoint joinPoint) {
//        logger.info("【开始执行】 : "+joinPoint.getTarget().getClass().toString()
//                +" 类中的 "+joinPoint.getSignature().getName()+" 方法") ;
    }

    @AfterReturning("allFunctions()")
    public void doAfter(JoinPoint joinPoint) {
//        logger.info("【成功执行】 : "+joinPoint.getTarget().getClass().toString()
//                +" 类中的 "+joinPoint.getSignature().getName()+" 方法") ;
    }

    @AfterThrowing(pointcut = "allFunctions()", throwing="e")
    public void doAfterThrowing(JoinPoint joinPoint,Exception e) {
        logger.error("------出现异常 : "+joinPoint.getTarget().getClass().toString()
                +" 类中的 "+joinPoint.getSignature().getName()+" 方法出现异常,\n"
                +"异常信息 : \n"+e.getMessage());
/*        logger.error("------出现异常 : "+joinPoint.getTarget().getClass().toString()
                +" 类中的 "+joinPoint.getSignature().getName()+" 方法出现异常,\n"
                +"异常信息 : \n"+e.getMessage()+"\n异常跟踪栈:"+ Arrays.toString(e.getStackTrace()));*/
    }
}
